﻿using LuDragon.Data.Config;
using System;
using System.Collections.Concurrent;
using System.Data;
using System.Data.SqlClient;
using System.Threading.Tasks;

namespace LuDragon.Data.DataHandler
{   
    public class WriteConnectionPool
    {
        private static WriteConnectionPool _cpool = null; //池管理对象
        private static readonly object _objlock = typeof(WriteConnectionPool); //池管理对象实例
        private readonly int _size = 10; //池中连接数
        private int _useCount = 0; //已经使用的连接数
        private static ConcurrentQueue<IDbConnection> _ConcurrenProducts { get; set; }
        private WriteConnectionPool()
        {
            _size = 100;
            _ConcurrenProducts = new ConcurrentQueue<IDbConnection>();
        }

        /// <summary>
        /// 创建获取连接池对象
        /// </summary>
        public static WriteConnectionPool Pool
        {
            get
            {
                lock (_objlock)
                {
                    return _cpool ?? (_cpool = new WriteConnectionPool());
                }
            }
        }

        /// <summary>
        /// 获取池中的连接
        /// </summary>
        public IDbConnection Connection
        {
            get
            {
                IDbConnection tmp;
                _ConcurrenProducts.TryDequeue(out tmp);
                if (tmp != null)
                {
                    _useCount++;
                    return tmp;
                }
                try
                {
                    Parallel.Invoke(() =>
                    {
                        IDbConnection conn2 = new SqlConnection(AppConfig.WriteDbContext);
                        conn2.Open();
                        tmp = conn2;
                    });
                }
                catch (Exception ex)
                {
                    throw new Exception("获取写数据库连接错误！", ex);
                }
                return tmp;
            }
        }
        /// <summary>
        /// 关闭连接,加连接回到池中
        /// </summary>
        /// <param name="con"></param>
        public void CloseConnection(IDbConnection con)
        {
            if (con == null) return;
            Parallel.Invoke(() =>
            {
                if (_useCount >= _size)
                {
                    con.Close();
                }
                else
                {
                    _ConcurrenProducts.Enqueue(con);
                    _useCount--;
                }
            });
        }
    }
}